using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using EnvDTE;
using Microsoft.VisualStudio.Modeling;

namespace DslCrossModelFramework {
    /// <summary>
    /// <see cref="ModelFile"/> implementation that represents a model file in the currently open solution
    /// </summary>
    public class SolutionModelFile : ModelFile, IDynamicStoreModelFile {

        public SolutionModelFile(ProjectItem projectItem, DslToolsPackageInfo packageInfo) {

            this.referencingProject = projectItem.ContainingProject.Name;
            this.projectItemPath = projectItem.get_FileNames(1);

            lastUpdated = File.GetLastWriteTimeUtc(projectItemPath);

            if (projectItem.ContainingProject.Object is VSLangProj.VSProject) {
                VSLangProj.VSProject vsproj = projectItem.ContainingProject.Object as VSLangProj.VSProject;
                owningAssembly = vsproj.Project.Properties.Item("AssemblyName").Value.ToString();
                defaultNamespace = vsproj.Project.Properties.Item("DefaultNamespace").Value.ToString() + ".";
            }
            this.dslPackageId = packageInfo.Guid;
            this.name = projectItem.Name;
            this.uniqueModelFileReference = GetModelFileUniqueReference(projectItem, packageInfo);
        }

        private DateTime lastUpdated;

        private string defaultNamespace = string.Empty;

        /// <summary>
        /// Gets the contents of the DSL model file.
        /// </summary>
        /// <exception cref="FileNotFoundException">If the model file that was found at the time of discovery is no longer found.</exception>
        /// <returns></returns>
        public override string GetContents() {
            if(!File.Exists(projectItemPath)) {
                throw new FileNotFoundException(string.Format("The model file at '{0}' could not be found.", projectItemPath));
            }
            this.lastUpdated = File.GetLastWriteTimeUtc(projectItemPath);
            return System.IO.File.ReadAllText(projectItemPath);
        }

        /// <summary>
        /// Gets the referencing project.
        /// </summary>
        /// <value>The referencing project.</value>
        public string ReferencingProject {
            get { return referencingProject; }
        }
        private readonly string referencingProject;

        /// <summary>
        /// Gets the project item path.
        /// </summary>
        /// <value>The project item path.</value>
        public string ProjectItemPath {
            get { return projectItemPath; }
        }
        private readonly string projectItemPath;

        /// <summary>
        /// Gets the unique model file reference.
        /// </summary>
        /// <value>The unique model file reference.</value>
        public override string UniqueModelFileReference {
            get { return uniqueModelFileReference; }
        }
        private readonly string uniqueModelFileReference;

        private string GetModelFileUniqueReference(ProjectItem projectItem, DslToolsPackageInfo packageInfo) {
            string projectItemName = Path.GetFileName(projectItem.Name);
            if(projectItem.ContainingProject != null) {
                string projectFolder = Path.GetDirectoryName(projectItem.ContainingProject.FullName);
                if(projectItemPath.StartsWith(projectFolder)) {
                    projectItemName = defaultNamespace +
                        Path.GetFileName(
                            projectItemPath.Replace(projectFolder, "").Replace("\\", ".").TrimStart('.'));
                }
            }
            return string.Format(CultureInfo.InvariantCulture, "amr://{0}/{1}/{2}", packageInfo.Guid.ToString(), owningAssembly, projectItemName);
        }

        private Store dynamicStore;

        public bool HasDynamicStore {
            get { return dynamicStore != null; }
        }

        public Store DynamicStore {
            get { return dynamicStore; }
        }

        public override bool IsDirty {
            get { return File.GetLastWriteTimeUtc(this.projectItemPath) > this.lastUpdated; }
        }

        public override string LocalFilePath {
            get { return projectItemPath; }
        }
        
        public void RegisterDynamicStore(Store store) {
            dynamicStore = store;
            DynamicStoreFound(this, new DynamicModelFileEventArgs(store, this));
            dynamicStore.StoreDisposing += new System.EventHandler(dynamicStore_StoreDisposing);
        }

        public event EventHandler<DynamicModelFileEventArgs> DynamicStoreFound;

        void dynamicStore_StoreDisposing(object sender, System.EventArgs e) {

            StoreDisposed(this, new DynamicModelFileEventArgs(dynamicStore, this));
            dynamicStore = null;
        }

        public event EventHandler<DynamicModelFileEventArgs> StoreDisposed;

        public override Image GetContainerIcon() {
            return Image.FromStream(
                GetType().Assembly.GetManifestResourceStream(
                    string.Format("{0}.Resources.genericProject.bmp", GetType().Namespace)));
        }



    }
}